#ifndef RANGE_H
#define RANGE_H

class range
{
public:
	explicit range( int start, int end, int stride = 1 ) 
		: start_(start), end_(end), stride_(stride) {}
	range( const range& r )
		{ start_ = r.start_; end_ = r.end_; stride_ = r.stride_; }
		
	range() {}
	~range() {}
	
	inline int start() const  { return start_; }
	inline int end() const    { return end_; }
	inline int stride() const { return stride_; }
	inline int length() const { return ( end_ - start_ ) / stride_ + 1; }
	
	inline range& operator=( const range& r )
	{
		start_ = r.start_;
		end_ = r.end_;
		stride_ = r.stride_;
		return *this;
	}
	
	inline int operator()( int i ) const { return start_ + i * stride_; }
	inline int operator[]( int i ) const { return start_ + i * stride_; }
	
	inline range operator+( int shift ) const { return range( start_ + shift, end_ + shift, stride_ ); }
	inline range operator-( int shift ) const { return range( start_ - shift, end_ - shift, stride_ ); }
	inline range operator*( int factor) const { return range( start_ * factor, end_ * factor, stride_ ); }
	inline range operator/( int factor) const { return range( start_ / factor, end_ / factor, stride_ ); }
	
	inline range& operator+=( int shift ) { start_ += shift; end_ += shift; return *this;}
	inline range& operator-=( int shift ) { start_ -= shift; end_ -= shift; return *this;}
	inline range& operator*=( int factor) { start_ *= factor; end_ *= factor; return *this;}
	inline range& operator/=( int factor) { start_ /= factor; end_ /= factor; return *this;}

private:
	int start_, end_, stride_;
};

struct range_all : public range {};

#endif //!< RANGE_H